package api

import (
	"github.com/gin-contrib/cors"
	"github.com/gin-contrib/sse"
	"github.com/gin-gonic/gin"
	"goexample.com/vulscaner/assets"
	"goexample.com/vulscaner/common"
	"html/template"
	"log/slog"
	"net/http"
	"regexp"
	"strconv"
)

func startDefaultScan(c *gin.Context) {
	type scanHostParam struct {
		HostParam string `json:"host"`
	}
	var scanHostParamData scanHostParam
	if err := c.BindJSON(&scanHostParamData); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	cidrIp := scanHostParamData.HostParam
	reIPV4 := regexp.MustCompile(`^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}(/(([1-2]\d)|(3[0-2])|(\d)))?$`)
	if !reIPV4.MatchString(cidrIp) {
		c.JSON(403, gin.H{
			"Status":  "0",
			"Message": "请提交合法的IPV4地址",
		})
		return
	} else {
		if CmdDone() {
			ExecScan(cidrIp)
			c.JSON(200, gin.H{
				"Status":  "1",
				"Message": "扫描任务已成功执行",
			})
		} else {
			c.JSON(403, gin.H{
				"Status":  "0",
				"Message": "当前扫描未完成",
			})
		}
	}
}

func taskStatus(c *gin.Context) {
	if CmdDone() {
		c.JSON(200, gin.H{
			"Status":  "1",
			"Message": "当前扫描任务已结束或未开始",
		})
	} else {
		c.JSON(200, gin.H{
			"Status":  "0",
			"Message": "当前扫描任务仍在进行中",
		})
	}
}

func xrayHtml(c *gin.Context) {
	id := c.Query("id")
	if id != "" {
		_, htmlFile := VulXrayOutFileName(id)
		c.JSON(200, gin.H{
			"Status":  "1",
			"Message": "",
			"Result":  htmlFile,
		})
	} else {
		c.JSON(403, gin.H{
			"Status":  "0",
			"Message": "缺少关键参数: id",
		})
		return
	}
}

func liveHosts(c *gin.Context) {
	id := c.Query("taskid")
	if id != "" {
		ipPorts := DetectLiveHosts(id)
		c.JSON(200, gin.H{
			"Status":  "1",
			"Message": "查询成功",
			"Result":  ipPorts,
		})
	} else {
		c.JSON(403, gin.H{
			"Status":  "0",
			"Message": "查询失败",
		})
		return
	}
}

func vulInfo(c *gin.Context) {
	id := c.Query("taskid")
	if id != "" {
		vulLists := DetectVulLists(id)
		c.JSON(200, gin.H{
			"Status":  "1",
			"Message": "",
			"Result":  vulLists,
		})
	} else {
		c.JSON(403, gin.H{
			"Status":  "0",
			"Message": "缺少关键参数 taskid",
		})
		return
	}
}

func scanHistory(c *gin.Context) {
	historyEntrys := allEntry()
	if historyEntrys == nil {
		c.JSON(500, gin.H{
			"Status":  "0",
			"Message": "服务器错误",
		})
		return
	}
	c.JSON(200, gin.H{
		"Status":  "1",
		"Message": "",
		"Result":  historyEntrys,
	})
}

func showOut(c *gin.Context) {
	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")

	for msg := range messageChan {
		c.Render(-1, sse.Event{
			Id:    strconv.Itoa(sseId),
			Event: "message",
			Data:  msg,
		})
		c.Writer.Flush()
	}
}

func WebStarter() {
	bindAdd := "127.0.0.1:8800"
	router := gin.Default()
	router.Use(cors.Default())

	if common.DEBUG_MODE {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}

	// router.Static("/static", "./static/web")
	router.StaticFS("/assets", http.FS(assets.LoadFile()))

	tmpl := template.Must(template.New("").ParseFS(assets.WebFiles, "web/*.html"))
	router.SetHTMLTemplate(tmpl)

	router.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html", nil)
	})

	// router.GET("/api/xrayHtml", xrayHtml)

	/* 漏洞信息 */
	router.GET("/api/vul/info", vulInfo)
	/* 扫描信息 */
	router.GET("/api/scan/status", taskStatus)
	router.GET("/api/scan/liveHosts", liveHosts)
	router.GET("/api/scan/history", scanHistory)
	router.POST("/api/scan/start", startDefaultScan)
	/* SSE传输命令输出 */
	router.GET("/api/scan/info", showOut)

	err := router.Run(bindAdd)
	if err != nil {
		slog.Error(err.Error())
		return
	}
}
